/**
 * axios封装的需求
 *  1、创建一个axios实例，因为可能会有多个实例，有不同的配置。
 *  2、请求拦截器：如果有token进行头部携带 ==> vuex ==> 本地存储
 *  3、响应连接器：（1）剥离无效数据，（2）处理token失效
 *      token失效（没有token）
 *          3.2.1 清空无效的用户信息
 *          3.2.2 登录后需要重新跳转回原来的页面，所以要 获取当前的路由地址 并 传递给登录路由。
 *          3.2.3 路由跳转，携带当前路由
 *      获取路由地址（/user?a=100&b=20）：
 *          （1）在组件中
 *              $route.path ===> /user
 *              $route.fullpath ===> /user?a=100&b=20
 *          （2）在js模块中
 *             当前路由地址 router.currentRoute.value.fullpath ===> /user?a=100&b=20
 *              router.currentRoute是一个vue3的ref对象
 *          （3）uri编码
 *              当模块通过url传参时(/user?a=100&b=20)，为了防止解析地址出问题，必须要用encodeURIComponent()函数进行特殊字符的编码转换，如对?、=进行转码
 *              const fullPath = encodeURIComponent("/user?a=100&b=20")
 *              编码：encodeURIComponent()
 *              解码：decodeURIComponent()
 *  4、导出一个函数，调用当前的axios实例发送请求，返回值为promise
 * */

import axios from "axios";
import store from "@/store";
import router from "@/router";

// 导出基准地址，原因：其他地方可能不是通过axios发送请求的（图片上传），需要使用到基准地址
// export const baseURL = "https://apipc-xiaotuxian-front.itheima.net";
export const baseURL = "https://pcapi-xiaotuxian-front-devtest.itheima.net/";

// 1、创建一个axios实例
const instance = axios.create({
    // axios配置信息，常用配置：baseURL、timeout
    baseURL,
    timeout: 5000
});

// 2、请求拦截器
instance.interceptors.request.use(config => {
    // 进行请求业务修改：如果有token进行头部携带
    // 2.1 获取用户信息，用户信息存储在Vuex中
    const profile = store.state.user.profile;
    // 2.2 判断是否存在token
    if (profile.token) {
        // token存在，设置请求头
        config.headers.Authorization = `Bearer ${profile.token}`;
    }
    return config;
}, error => {
    // 拦截失败
    return Promise.reject(error);
});

// 3、响应拦截器
instance.interceptors.response.use(response => {
    // 3.1 剥离无效数据
    return response.data;
}, error => {
    // 3.2 处理错误
    // 根据状态码，判断处理类型
    // 401：没有权限，调整到登录
    if (error.response && error.response.status === 401) {
        // 跳转到登录之前需要的处理
        // 3.2.1 清空无效的用户信息
        store.commit("user/updateUser", {});
        // 3.2.1.1 获取当前的路由地址
        // （1）在组件中获取路由地址
        const fullpath = router.currentRoute.value.fullPath;
        // （2）进行转码：encodeURIComponent()进行转码，防止地址解析出现问题
        const fullpathEncode = encodeURIComponent(fullpath);
        // 3.2.3 路由跳转，携带当前路由
        router.push("/login?redirectUrl=" + fullpathEncode);
    }

    return Promise.reject(error);
});

/**
 * 请求工具：发送请求
 * @param url 请求的url
 * @param method 请求的方式：get、post、put、delete
 * @param submitData 请求时携带的参数
 */
export default (url, method, submitData) => {
    return instance({
        url,
        method,
        // 1. 如果是get请求，需要使用params来传递submitData ==> ?a=10&c=10
        // 2. 如果不是get请求，需要使用data来传递submitData ==> 请求体传参
        // [] 设置一个动态的key，写js表达式，js表达式的执行结果当作KEY
        //      const user={name:"xyz", age:10} ==> user["name"] ==> user[10>8?"name":"age"]
        // method参数：get,Get,GET  转换成小写再来判断
        // 在对象，['params']:submitData ===== params:submitData 这样理解
        [method.toLowerCase() === "get" ? "params" : "data"]: submitData
    });
};
